package com.spring.framework.aop;

import com.spring.framework.aop.aspect.MyAdvice;
import com.spring.framework.aop.support.MyAdviceSupport;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Map;

/**
 * @author ππ
 * @date 2020-11-18 11:30
 * @desc
 */

public class MyJdkDynamicAopProxy implements InvocationHandler {
    private MyAdviceSupport config;
    public MyJdkDynamicAopProxy(MyAdviceSupport config) {
        this.config = config;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        Map<String, MyAdvice> advices = this.config.getAdvices(method);
        // 以下也是硬编码，理解原理
        Object returnValue;
        try {
            invokeAdviceMethod(advices.get("before"));

            returnValue = method.invoke(config.getTargetInstance(),args);

            invokeAdviceMethod(advices.get("after"));
        }catch (Exception e){
            invokeAdviceMethod(advices.get("afterThrowing"));
            throw e;
        }


        return returnValue;
    }

    private void invokeAdviceMethod(MyAdvice advice) throws InvocationTargetException, IllegalAccessException {
        if(null == advice) {
            return;
        }
        // 硬编码，Spring中AOP的参数为JoinPoint
        Method aspectMethod = advice.getAspectMethod();
        Object aspectBean = advice.getAspectBean();
        aspectMethod.invoke(aspectBean);
    }

    public Object getProxy() {
        return Proxy.newProxyInstance(this.getClass().getClassLoader(),config.getTargetClass().getInterfaces(),this);
    }
}
